package jp.sinmetal.trainer.action;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import jp.sinmetal.trainer.condition.EndBattleLogCondition;
import jp.sinmetal.trainer.dto.ConventionMemberDto;
import jp.sinmetal.trainer.entity.Convention;
import jp.sinmetal.trainer.entity.ConventionLog;
import jp.sinmetal.trainer.entity.ConventionMember;
import jp.sinmetal.trainer.form.ConventionForm;
import jp.sinmetal.trainer.service.ConventionFacadeService;

import org.apache.struts.util.TokenProcessor;
import org.seasar.framework.beans.util.Beans;
import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;

/**
 * 大会アクション
 * @author sin
 *
 */
public class ConventionAction extends AbstractAction {
    /**
     * 大会一覧
     * @author sin
     */
    public List<Convention> conventions;

    /**
     * 大会詳細
     * @author sin
     */
    public Convention convention;

    /**
     * 大会参加者一覧
     * @author sin
     */
    public List<ConventionMemberDto> conventionMemberDtos;

    /**
     * 対戦中大会ログ
     * @author sin
     */
    public List<ConventionLog> duringBattleConventionLogs;

    /**
     * 対戦終了大会ログ
     * @author sin
     */
    public List<ConventionLog> endBattleConventionLogs;

    /**
     * メッセージ
     * @author sin
     */
    public String message = "";

    /**
     * 大会アクションフォーム
     * @author sin
     */
    @ActionForm
    @Resource
    protected ConventionForm conventionForm;

    /**
     * 終了条件マップ
     * <key,表示用文言>
     * @author sin
     */
    @Resource
    public Map<Integer, String> endStateMap;

    /**
     * HttpRequest
     * @author ishimura
     */
    @Resource
    protected HttpServletRequest request;

    /**
     * 大会ファサードサービス
     * @author sin
     */
    @Resource
    protected ConventionFacadeService conventionFacadeService;

    /**
     * エントリーポイント
     * 大会一覧表示
     * @author sin
     *
     * @return
     */
    @Execute(validator = false)
    public String index() {
        conventions = conventionFacadeService.findAllConvention();

        return "list.jsp";
    }

    /**
     * 大会詳細
     * @author sin
     *
     * @return
     */
    @Execute(input = "/convention", urlPattern = "{conventionId}")
    public String show() {
    	Integer conventionId = Integer.parseInt(conventionForm.conventionId);
    	conventionForm.href = String.format("%s", conventionForm.conventionId);
    	conventionForm.totalRec = conventionFacadeService.getEndBattleConventionLogCount(conventionId).toString();

    	convention = conventionFacadeService.findConventionById(conventionId);
    	conventionMemberDtos = conventionFacadeService.findConventionMemberByConventionId(conventionId);
    	duringBattleConventionLogs = conventionFacadeService.findDuringBattleConventionLogAll(conventionId);
    	endBattleConventionLogs = conventionFacadeService.findEndBattleConventionLogs(EndBattleLogCondition.getInstance(conventionForm));
    	message = conventionFacadeService.matching(conventionId, false);
        return "show.jsp";
    }

    /**
     * 大会編集
     * @author sin
     *
     * @return
     */
    @Execute(validator = false, urlPattern = "edit/{conventionId}")
    public String edit() {
    	TokenProcessor.getInstance().saveToken(request);

        Convention entity = conventionFacadeService.findConventionById(Integer.valueOf(conventionForm.conventionId));
        Beans.copy(entity, conventionForm).dateConverter(DATE_FORMAT).execute();
        return "edit.jsp";
    }

    /**
     * ヘルプ
     * やっつけで作ってる
     * @author sin
     *
     * @return
     */
    @Execute(validator = false)
    public String help() {
    	return "help.jsp";
    }

    /**
     * 大会作成
     * @author sin
     *
     * @return
     */
    @Execute(validator = false)
    public String create() {
    	TokenProcessor.getInstance().saveToken(request);
        return "create.jsp";
    }

    /**
     * 大会作成サービス呼び出し
     * @author sin
     *
     * @return
     */
    @Execute(input = "create.jsp", redirect = true)
    public String insert() {
    	if (!TokenProcessor.getInstance().isTokenValid(request, true)) {
    		//二重投稿時はトップページへ
    		return "/convention/";
    	}

    	if (!memberInfo.isLogin()) {
    		return "/authentication/";
    	}

        Convention entity = Convention.getInstance(conventionForm);

        entity.memberId = memberInfo.memberId;
        conventionFacadeService.insertConvention(entity);
        return String.format("/convention/%s", entity.conventionId);
    }

    /**
     * 大会更新サービス呼び出し
     * @author sin
     *
     * @return
     */
    @Execute(input = "edit.jsp", redirect = true)
    public String update() {
    	Convention entity = Convention.getInstance(conventionForm);

    	if (!TokenProcessor.getInstance().isTokenValid(request, true)) {
    		return String.format("/convention/%s", entity.conventionId);
    	}

        entity.memberId = memberInfo.memberId;
        conventionFacadeService.updateConvention(entity);
        return String.format("/convention/%s", entity.conventionId);
    }

    /**
     * マッチング
     * @author sin
     *
     * @return
     */
    @Execute(validator = false, urlPattern = "matching/{conventionId}", redirect = true)
    public String matching() {
    	Integer conventionId = Integer.parseInt(conventionForm.conventionId);
    	message = conventionFacadeService.matching(conventionId, true);
    	return String.format("/convention/%s", conventionForm.conventionId);
    }

    /**
     * ログインユーザが主催者かを返す
     * JSP側で利用
     * @author sin
     *
     * @return
     */
    public boolean getOwnerFlag() {
    	return (convention != null && convention.memberId.equals(memberInfo.memberId));
    }

    /**
     * ログインユーザがエントリーしているかを返す
     * JSP側で利用
     * @author sin
     *
     * @return
     */
    public boolean getEntryFlag() {
    	if (convention == null) {
    		return false;
    	}

    	for (ConventionMember conventionMember : convention.conventionMembers) {
    		if (conventionMember.memberId.equals(memberInfo.memberId)) {
    			return true;
    		}
    	}
    	return false;
    }

    /**
     * 自分がマッチングされているConventionLogIdを返す
     * JSP側で利用
     * @author sin
     *
     * @return
     */
    public int getMyMatchingConventionLogId() {
    	if (duringBattleConventionLogs == null) {
    		return 0;
    	}

    	for (ConventionLog conventionLog : duringBattleConventionLogs) {
    		if (conventionLog.conventionMember1st.memberId.equals(memberInfo.memberId)
    				|| conventionLog.conventionMember2nd.memberId.equals(memberInfo.memberId)) {
    			return conventionLog.conventionLogId;
    		}
    	}
    	return 0;
    }

    /**
     * ログインユーザのConventionMemberIdを返す
     * JSP側で利用
     * @author sin
     *
     * @return
     */
    public int getMyConventionMemberId() {
    	if (convention == null) {
    		return 0;
    	}

    	for (ConventionMember conventionMember : convention.conventionMembers) {
    		if (conventionMember.memberId.equals(memberInfo.memberId)) {
    			return conventionMember.conventionMemberId;
    		}
    	}
    	return 0;
    }
}